# @Time : 2020/7/20 11:24
# @Author : Fioman 
# @Phone : 13149920693
"""
把一幅图像内的像素点放置到另外一幅图像内的指定位置,这个过程称为重映射.
opecv提供了多种重映射的方式,但是我们有时希望使用自定义的方式完成重映射.
Opecv内置的重映射函数cv.remap()提供了更方便,更自由的映射方式.
dst = cv.remap(src,map1,map2,interplolation[,boardMode,[,boarderValue]])
式中:
dst 代表目标图像,它和src具有相同的大小和类型
src 代表原始图像
map1 有两种可能: 表示(x,y)点的一个映射, 表示CV_16SC2, CV_32FC1, CV32FC@类型(x,y)点的x值.
map2 同样有两种可能的值: 当map1表示(x,y)时,该值是空,当map1表示(x,y)点的x值时,该值时CV_16UC1,CV_32FC1类型(x,y)点的y值.

interpolation 表示插值方式,这里不支持INTER_AREA方法.

使用cv.remap()完成数组映射,将目标数组内的所有像素点都映射为原始图像内第0行第三列上的像素点,以此来了解函数cv.remap()内参数map1和map2的使用情况.
> 根据题目要求,可以确定:
1> 用来指定列的参数map1 (mapx) 内的值均为3
2> 用来指定行的参数map2 (mapy) 内的值均为0
"""

import cv2 as cv
import numpy as np

img = np.random.randint(0, 255, size=[4, 5], dtype=np.uint8)
print("img = \n", img)
mapx = np.ones(img.shape, np.float32) * 3  # 第三列
mapy = np.ones(img.shape, np.float32) * 0  # 第0行 值为333.

rst = cv.remap(img, mapx, mapy, cv.INTER_LINEAR)
print("mapx = \n", mapx)
print("mapy = \n", mapy)
print("rst = \n", rst)

"""
使用重映射进行复制图像:
1> 将map1的值设定为对应位置上的x轴坐标值
2> 将map2的值设定为对应位置上的y轴坐标值.
通过上述处理后,可以将函数cv.remap()实现图像复制.
"""

img = np.random.randint(0, 256, size=[4, 5], dtype=np.uint8)
rows, cols = img.shape
mapx = np.zeros(img.shape, np.float32)
mapy = np.zeros(img.shape, np.float32)

for i in range(rows):
    for j in range(cols):
        mapx.itemset((i, j), j)
        mapy.itemset((i, j), i)

rst = cv.remap(img, mapx, mapy, cv.INTER_LINEAR)
print("img = \n", img)
print("mapx = \n", mapx)
print("mapy = \n", mapy)
print("rst = \n", rst)

"""
通过本例可以观察到,参数mapx和参数mapy分别设置了x轴方向的坐标和y轴方向的坐标.函数cv.remap()利用参数mapx,mapy
所组成的数组构造的映射关系实现了图像的复制.
例如:rst 中的四项试点[3,4]在src内的x,y坐标如下:
x轴坐标取决于mapx中的mapx[3,4]的值,为4
y轴坐标取决于mapy中的mapy[3,4]的值,为3
这说明rst[3,4]来源于原始图像src的第4列(x轴方向,由mapx[3,4]决定)
第三行(y轴方向,由mapy[3,4]决定)
下面将复制一幅图像
"""
img = cv.imread("lenaColor.png", cv.IMREAD_COLOR)
rows, cols = img.shape[:2]
mapx = np.zeros(img.shape[:2], np.float32)
mapy = np.zeros(img.shape[:2], np.float32)

for i in range(rows):
    for j in range(cols):
        mapx.itemset((i, j), j)
        mapy.itemset((i, j), i)
rst = cv.remap(img, mapx, mapy, cv.INTER_LINEAR)
cv.imshow("original", img)
cv.imshow("result", rst)
cv.waitKey(0)
cv.destroyAllWindows()

"""
使用重映射实现绕x轴翻转.
如果想让图像绕着x轴翻转,意味着在映射过程中:
1> x坐标轴的值保持不变.
2> y轴坐标以x轴为对称轴进行交换
反映到map1和map2上:
1> map1保持不变
2> map2值调整为总行数-1-当前行号
"""
mapx = np.zeros(img.shape[:2], np.float32)
mapy = np.zeros(img.shape[:2], np.float32)

for i in range(rows):
    for j in range(cols):
        mapx.itemset((i, j), j)
        mapy.itemset((i, j), rows - 1 - i)
rst = cv.remap(img, mapx, mapy, cv.INTER_LINEAR)

print("img = \n", img)
print("mapx = \n", mapx)
print("mapy = \n", mapy)
print("rst = \n", rst)
cv.imshow("rstFlipX", rst)
cv.waitKey(0)

"""
绕着y轴翻转.
表现在mapy的值就是行号不变,但是mapx的值就是列好要改变.
等于中列数 - i - 1
"""
mapx = np.zeros(img.shape[:2], dtype=np.float32)
mapy = np.zeros(img.shape[:2], dtype=np.float32)
for i in range(rows):
    for j in range(cols):
        mapx.itemset((i, j), cols - 1 - j)
        mapy.itemset((i, j), i)

rst = cv.remap(img, mapx, mapy, cv.INTER_LINEAR)

cv.imshow("FlipY", rst)
cv.waitKey(0)

"""
实现x轴和y轴同时翻转
"""
mapx = np.zeros(img.shape[:2], dtype=np.float32)
mapy = np.zeros(img.shape[:2], dtype=np.float32)

for i in range(rows):
    for j in range(cols):
        mapx.itemset((i, j), cols - 1 - j)
        mapy.itemset((i, j), rows - 1 - i)

rst = cv.remap(img, mapx, mapy, cv.INTER_LINEAR)
cv.imshow("FlipXY", rst)
cv.waitKey(0)


"""
实现x轴和y轴的值互换
"""
mapx = np.zeros(img.shape[:2],dtype=np.float32)
mapy = np.zeros(img.shape[:2],dtype=np.float32)

for i in range(rows):
    for j in range(cols):
        mapx.itemset((i,j),i)
        mapy.itemset((i,j),j)

res = cv.remap(img,mapx,mapy,cv.INTER_LINEAR)

cv.imshow("XChangedY",res)
cv.waitKey(0)











